// MfcDlgClientMainDlg.h : header file
//

#if !defined(AFX_MfcDlgClientMainDLG_H__66945FE6_6A79_49D6_9BB3_8F589F2A4CC6__INCLUDED_)
#define AFX_MfcDlgClientMainDLG_H__66945FE6_6A79_49D6_9BB3_8F589F2A4CC6__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////
// CMfcDlgClientMainDlg dialog
#include "../Common/inc/BlAPI.h"
#include "../Common/inc/BlClass.h"

#include <winsock2.h>
#include <math.h>

#define SERVER_PORT 9096
#define BLWM_LEN  6
#define MAX_BUFER_LEN   65535

#define	 ServerConfigIniFile	"./ServerConfig.ini"

class CMfcDlgClientMainDlg : public CDialog
{
	class CMyToolBar:public CToolBar
	{
	public:
		CMyToolBar(){}
		~CMyToolBar(){}
		void plInit(CWnd* pWnd,UINT id)
		{
			if(!Create(pWnd) || !LoadToolBar(IDR_TOOLBAR_MAIN))
			{
				TRACE0("Failed to Create Dialog Toolbar\n"); 
			}
			
			CRect rcClientOld; 
			CRect rcClientNew; 
			pWnd->GetClientRect(rcClientOld); 
			
			pWnd->RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0,reposQuery,rcClientNew);
			
			CPoint ptOffset(rcClientNew.left-rcClientOld.left,
				rcClientNew.top-rcClientOld.top);
			
			CRect rcChild;
			CWnd* pwndChild = pWnd->GetWindow(GW_CHILD); 
			while(pwndChild)
			{
				pwndChild->GetWindowRect(rcChild);
				ScreenToClient(rcChild); 
				rcChild.OffsetRect(ptOffset); 
				pwndChild->MoveWindow(rcChild,FALSE); 
				pwndChild = pwndChild->GetNextWindow();
			}
			
			CRect rcWindow;
			pWnd->GetWindowRect(rcWindow); 
			rcWindow.right += rcClientOld.Width() - rcClientNew.Width(); 
			rcWindow.bottom += rcClientOld.Height() - rcClientNew.Height(); 
			pWnd->MoveWindow(rcWindow,FALSE); 
			
			pWnd->RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);
		}
	};
	
	class CStaticClient: public CStatic
	{
	public:
		CStaticClient(){}
		~CStaticClient(){}
		BOOL plClickInMe(CPoint &p)
		{
			CPoint pt(p);
			GetParent()->ClientToScreen(&pt);
			ScreenToClient(&pt);
			
			BOOL b = false;
			CRect rt; 
			GetClientRect(&rt); 
			b =  rt.PtInRect(pt);
			if(b) return b; 
			
			CDC *pDC = GetDC();
			pDC->Ellipse(pt.x-5,pt.y-5,pt.x+5,pt.y+5);
			ReleaseDC(pDC);
			
			return b;
		}
	private:
	};
	
	class CClientProxy
	{
	public:
		CClientProxy(void *pParent):m_pParent(pParent)
		{}
		~CClientProxy(){}
		
	private:
		SOCKET m_ClientSocket;
		void*  m_pParent;
		
	public:	
		
		int Snap_Shot(char *recvBuffer)
		{
			BLWM dv = BL_WM_B1_0XB101;
			char szInput[BLWM_LEN];
			memcpy(szInput, (BYTE*)&dv, sizeof(DWORD));
			strcat(szInput,"\r\n");
			
			return GetData(szInput, recvBuffer);
		}
		
		int ConnectToServer(char ServerAddr[], int nPort=SERVER_PORT)
		{
			SOCKET *clientSocket = &m_ClientSocket;
			WSADATA wsaData;
			sockaddr_in serverAddr;
			int Ret;
			
			//Load Winsock.dll
			if((Ret = WSAStartup(MAKEWORD(2,2),&wsaData)) != 0)
			{
				return 0;
			}
			//Create client socket
			if((*clientSocket = socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
			{
				return 0;
			}
			//Fill sockaddr_in struct
			serverAddr.sin_family=AF_INET;
			serverAddr.sin_addr.s_addr=inet_addr(ServerAddr);
			serverAddr.sin_port=htons(SERVER_PORT);
			
			if(connect(*clientSocket,(sockaddr *)&serverAddr,sizeof(serverAddr)) == SOCKET_ERROR)
			{
				CString str;
				str.Format("Failed to connect to server %s:%d.\nYou can change the IP and Port from ServerConfig.ini.", ServerAddr, nPort);
				AfxMessageBox(str);
				closesocket(*clientSocket);
				WSACleanup();
				return 0;
			}
			
			return 1;
		}
		
		void DisConnect(){
			closesocket(m_ClientSocket);
			WSACleanup();
		}
		
	private:	
		int WriteSocket(char FAR *buf, int nWt)
		{
			int nCount = 0;
			int sC;
			while(nCount < nWt)
			{
				sC = send(m_ClientSocket, buf+nCount, nWt-nCount, 0);
				if(sC < 0) return sC;
				if(sC == 0)
					Sleep(100);
				nCount += sC;
			}
			return nCount;
		}
		
		int SetData(){
			return 1;
		}
		
		int GetData(char* InBuffer, char *recvBuffer)
		{
			if(WriteSocket(InBuffer, BLWM_LEN) == SOCKET_ERROR )
			{
				return 0;
			}
			
			char *pTmpBuf  = new char[MAX_BUFER_LEN];
			int nCopyLen = 0;
			while(true)
			{
				memset(pTmpBuf,0, MAX_BUFER_LEN);
				int retLen = recv(m_ClientSocket, pTmpBuf, MAX_BUFER_LEN, 0);
				if(retLen > 0) 
				{					
					memcpy(recvBuffer + nCopyLen, pTmpBuf, retLen);
					nCopyLen += retLen;
				}else if (retLen <= 0){
					if (retLen == SOCKET_ERROR)
					{
						delete []pTmpBuf;
						return 0;
					}
					break; 
				}
			}
			delete []pTmpBuf;
			
			return 1;
		}
		
	};
	
	class CMyBmp
	{
	public:
		CMyBmp(CMfcDlgClientMainDlg *p):m_hBmp(NULL),m_pBmpBits(NULL),m_pParent(p){}
		~CMyBmp(){}
		
		void plUser1(CWnd &myW, WPARAM w, LPARAM l)
		{  
			CDC *pDc = myW.GetDC();
			int n = (int)l;
			BYTE* pByte = (BYTE*)w; 
			CRect rect(60,110,300,300);
			myW.GetClientRect(&rect);
			ptShowBmp(pDc->m_hDC,pByte,n,&rect); 
			
			myW.ReleaseDC(pDc);
		}
		
	private:
		HBITMAP					m_hBmp;
		LPBYTE					m_pBmpBits;
		CMfcDlgClientMainDlg	*m_pParent;
		
		void ptShowBmp(HDC hDC,BYTE* pByte,int n, LPRECT pRect)
		{   
			HBITMAP	&h = m_hBmp;
			if(NULL==h) 
				h = ptCreateDIBSection(n,n,24,0); 
			::memcpy(m_pBmpBits,pByte,n*n*3);
			if(h)
				BOOL b = ptDrawDIBSectionOnDC(hDC,h,pRect);
		}
		
		HBITMAP ptCreateDIBSection( DWORD dwX, DWORD dwY, WORD wBits, BOOL Monochrome )
		{
			HBITMAP         hBitmap;
			int             nInfoSize;
			LPBITMAPINFO    pbmi;
			HDC             hRefDC;
			
			nInfoSize = sizeof( BITMAPINFOHEADER );
			if( wBits <= 8 )
				nInfoSize += sizeof(RGBQUAD) * (1 << wBits);
			if( ( wBits == 16 ) || ( wBits == 32 ) )
				nInfoSize += 3 * sizeof(DWORD);
			
			// Create the header big enough to contain color table and bitmasks if needed
			pbmi = (LPBITMAPINFO)malloc( nInfoSize );
			ZeroMemory( pbmi, nInfoSize );
			pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
			pbmi->bmiHeader.biWidth = dwX;
			pbmi->bmiHeader.biHeight = dwY;
			pbmi->bmiHeader.biPlanes = 1; 
			pbmi->bmiHeader.biBitCount = wBits;
			pbmi->bmiHeader.biCompression = BI_RGB; // override below for 16 and 32bpp
			
			switch( wBits )
			{
			case 24:
				// 24bpp requires no special handling
				break;
			case 16:
				{   // if it's 16bpp, fill in the masks and override the compression
					// these are the default masks - you could change them if needed
					LPDWORD pMasks = (LPDWORD)(pbmi->bmiColors);
					pMasks[0] = 0x00007c00;
					pMasks[1] = 0x000003e0;
					pMasks[2] = 0x0000001f;
					pbmi->bmiHeader.biCompression = BI_BITFIELDS;
				}
				break;
			case 32:
				{   // if it's 32bpp, fill in the masks and override the compression
					// these are the default masks - you could change them if needed
					LPDWORD pMasks = (LPDWORD)(pbmi->bmiColors);
					pMasks[0] = 0x00ff0000;
					pMasks[1] = 0x0000ff00;
					pMasks[2] = 0x000000ff;
					pbmi->bmiHeader.biCompression = BI_BITFIELDS; 
				}
				break;
			case 8:  
				{
					if(Monochrome)
					{
						int  i;
						for(i = 0; i<256; i++)
						{
							pbmi->bmiColors[i].rgbRed = i;
							pbmi->bmiColors[i].rgbGreen = i;
							pbmi->bmiColors[i].rgbBlue = i;
							pbmi->bmiColors[i].rgbReserved = 0;
						}
						pbmi->bmiHeader.biClrUsed = 256;
					}
					else
					{
						HPALETTE        hPal;
						PALETTEENTRY    pe[256];
						int             i;
						// at this point, prgb points to the color table, even 
						// if bitmasks are present
						hPal = ptCreateSpectrumPalette();
						GetPaletteEntries( hPal, 0, 256, pe );
						for(i=0;i<256;i++)
						{
							pbmi->bmiColors[i].rgbRed = pe[i].peRed;
							pbmi->bmiColors[i].rgbGreen = pe[i].peGreen;
							pbmi->bmiColors[i].rgbBlue = pe[i].peBlue;
							pbmi->bmiColors[i].rgbReserved = 0;
						}
						DeleteObject( hPal );
						pbmi->bmiHeader.biClrUsed = 256;
					}
				}
				break;
			case 4:
				{   // Use a default 16 color table for 4bpp DIBSections
					RGBTRIPLE       rgb[16] = { { 0x00, 0x00, 0x00 }, // black 
					{ 0x80, 0x00, 0x00 }, // dark red 
					{ 0x00, 0x80, 0x00 }, // dark green 
					{ 0x80, 0x80, 0x00 }, // dark yellow 
					{ 0x00, 0x00, 0x80 }, // dark blue 
					{ 0x80, 0x00, 0x80 }, // dark magenta 
					{ 0x00, 0x80, 0x80 }, // dark cyan 
					{ 0xC0, 0xC0, 0xC0 }, // light gray 
					//  { 0xC0, 0xDC, 0xC0 }, // money green 
					//  { 0xA6, 0xCA, 0xF0 }, // sky blue 
					//  { 0xFF, 0xFB, 0xF0 }, // cream 
					//  { 0xA0, 0xA0, 0xA4 }, // light gray 
					{ 0x80, 0x80, 0x80 }, // medium gray 
					{ 0xFF, 0x00, 0x00 }, // red 
					{ 0x00, 0xFF, 0x00 }, // green 
					{ 0xFF, 0xFF, 0x00 }, // yellow 
					{ 0x00, 0x00, 0xFF }, // blue 
					{ 0xFF, 0x00, 0xFF }, // magenta 
					{ 0x00, 0xFF, 0xFF }, // cyan 
					{ 0xFF, 0xFF, 0xFF } }; // white 
					int i;
					
					for(i=0;i<16;i++)
					{
						pbmi->bmiColors[i].rgbRed = rgb[i].rgbtRed;
						pbmi->bmiColors[i].rgbGreen = rgb[i].rgbtGreen;
						pbmi->bmiColors[i].rgbBlue = rgb[i].rgbtBlue;
						pbmi->bmiColors[i].rgbReserved = 0;
					}
					pbmi->bmiHeader.biClrUsed = 16;
				}
				break;
			case 1: // BW
				pbmi->bmiColors[0].rgbRed = pbmi->bmiColors[0].rgbGreen = pbmi->bmiColors[0].rgbBlue = 0;
				pbmi->bmiColors[1].rgbRed = pbmi->bmiColors[1].rgbGreen = pbmi->bmiColors[1].rgbBlue = 255;
				pbmi->bmiColors[0].rgbReserved = pbmi->bmiColors[1].rgbReserved = 0;
				break;
			}
			hRefDC = ::GetDC( NULL );
			hBitmap = CreateDIBSection( hRefDC, pbmi, DIB_RGB_COLORS, (void**)&m_pBmpBits, NULL, 0 );
			nInfoSize = GetLastError();
			::ReleaseDC( NULL, hRefDC );
			free( pbmi );
			if( hBitmap == NULL )
			{
				TCHAR   szTemp[64];
				wsprintf( szTemp, "Error %d", nInfoSize );
				::MessageBox( NULL, szTemp, "Error", MB_OK );
			}
			return hBitmap;
		}
			LPBITMAPINFO ptGetBITMAPINFOForDIBSection( HBITMAP hBitmap )
			{
				LPBITMAPINFO    pbmi;
				DIBSECTION      ds;
				LPRGBQUAD       prgb;
				
				GetObject( hBitmap, sizeof(DIBSECTION), &ds );
				// load the header and the bitmasks if present
				// per function comments above, we allocate space for a color 
				// table even if it is not needed 
				if( ds.dsBmih.biCompression == BI_BITFIELDS )
				{   // has a bitmask - be sure to allocate for and copy them
					pbmi = (BITMAPINFO*)malloc( sizeof(BITMAPINFOHEADER) + (3*sizeof(DWORD)) + (256*sizeof(RGBQUAD)) );
					CopyMemory( &(pbmi->bmiHeader), &(ds.dsBmih), sizeof(BITMAPINFOHEADER) + (3*sizeof(DWORD)) );
					prgb = (LPRGBQUAD)&(pbmi->bmiColors[3]);
				}
				else
				{   // no bitmask - just the header and color table
					pbmi = (BITMAPINFO*)malloc( sizeof(BITMAPINFOHEADER) + (256*sizeof(RGBQUAD)) );
					CopyMemory( &(pbmi->bmiHeader), &(ds.dsBmih), sizeof(BITMAPINFOHEADER) );
					prgb = pbmi->bmiColors;
				}
				// at this point, prgb points to the color table, even 
				// if bitmasks are present
				
				// Now for the color table
				if( ( ds.dsBm.bmBitsPixel * ds.dsBm.bmPlanes ) <= 8 )
				{   // the DIBSection is 256 color or less (has color table)
					HDC             hMemDC;
					HBITMAP         hOldBitmap;
					hMemDC = CreateCompatibleDC( NULL );
					hOldBitmap = (HBITMAP)SelectObject( hMemDC, hBitmap );
					GetDIBColorTable( hMemDC, 0, 1<<(ds.dsBm.bmBitsPixel*ds.dsBm.bmPlanes), prgb );
					SelectObject( hMemDC, hOldBitmap );
					DeleteDC( hMemDC );
				}
				else
				{   // the DIBSection is >8bpp (has no color table) so make one up
					HPALETTE        hPal;
					PALETTEENTRY    pe[256];
					int             i;
					
					// where are we going to get the colors? from a spectrum palette
					hPal = ptCreateSpectrumPalette();
					GetPaletteEntries( hPal, 0, 256, pe );
					for(i=0;i<256;i++)
					{
						prgb[i].rgbRed = pe[i].peRed;
						prgb[i].rgbGreen = pe[i].peGreen;
						prgb[i].rgbBlue = pe[i].peBlue;
						prgb[i].rgbReserved = 0;
					}
					DeleteObject( hPal );
					pbmi->bmiHeader.biClrUsed = 256;
				}
				return pbmi;
			} 
			HBITMAP ptGetBmpFromClipboard()
			{
				HBITMAP		h = NULL;
				if (!::IsClipboardFormatAvailable(CF_BITMAP)) 
				{ 
					return h;
				}
				if ( ::OpenClipboard ( 0 ) ) 
				{
					h = (HBITMAP)GetClipboardData( CF_BITMAP ); 
					
					::CloseClipboard();
				}
				
				return h;
			}
			HPALETTE ptCreatePaletteForDIBSection( HBITMAP hBitmap )
			{
				BITMAP      bm;
				HPALETTE    hPalette;
				
				// Get the color depth of the DIBSection
				GetObject( hBitmap, sizeof(BITMAP), &bm );
				// If the DIBSection is 256 color or less, it has a color table
				if( ( bm.bmBitsPixel * bm.bmPlanes ) <= 8 )
				{
					HDC             hMemDC;
					HBITMAP         hOldBitmap;
					RGBQUAD         rgb[256];
					LPLOGPALETTE    pLogPal;
					WORD            i;
					int             nColors;
					
					// Find out how many colors are in the color table
					nColors = 1 << ( bm.bmBitsPixel * bm.bmPlanes );
					// Create a memory DC and select the DIBSection into it
					hMemDC = CreateCompatibleDC( NULL );
					hOldBitmap = (HBITMAP)SelectObject( hMemDC, hBitmap );
					// Get the DIBSection's color table
					GetDIBColorTable( hMemDC, 0, nColors, rgb );
					// Create a palette from the color table
					pLogPal = (LOGPALETTE*)malloc( sizeof(LOGPALETTE) + (nColors*sizeof(PALETTEENTRY)) );
					pLogPal->palVersion = 0x300;
					pLogPal->palNumEntries = nColors;
					for(i=0;i<nColors;i++)
					{
						pLogPal->palPalEntry[i].peRed = rgb[i].rgbRed;
						pLogPal->palPalEntry[i].peGreen = rgb[i].rgbGreen;
						pLogPal->palPalEntry[i].peBlue = rgb[i].rgbBlue;
						pLogPal->palPalEntry[i].peFlags = 0;
					}
					hPalette = CreatePalette( pLogPal );
					// Clean up
					free( pLogPal );
					SelectObject( hMemDC, hOldBitmap );
					DeleteDC( hMemDC );
				}
				else   // It has no color table, so make one up
				{
					hPalette = ptCreateSpectrumPalette();
				}
				return hPalette;
			}
			HPALETTE ptCreateSpectrumPalette( void ) 
			{                 
				HPALETTE hPal;
				LPLOGPALETTE lplgPal;
				BYTE red, green, blue;
				int i; 
				
				lplgPal = (LPLOGPALETTE)GlobalAlloc( GPTR, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256 ); 
				if (!lplgPal)
					return NULL;
				
				lplgPal->palVersion = 0x300;
				lplgPal->palNumEntries = 256;
				
				red = green = blue = 0;
				for (i = 0; i < 256; i++) {
					lplgPal->palPalEntry[i].peRed   = red;
					lplgPal->palPalEntry[i].peGreen = green;
					lplgPal->palPalEntry[i].peBlue  = blue;
					lplgPal->palPalEntry[i].peFlags = (BYTE)0;
					
					if (!(red += 32))
						if (!(green += 32))
							blue += 64;
				}
				hPal = CreatePalette(lplgPal);
				GlobalFree(lplgPal);
				return hPal;
			}
			
			BOOL ptDrawDIBSectionOnDC( HDC hDC, HBITMAP hBitmap, LPRECT pxdRect )
			{
				DIBSECTION  ds;
				HPALETTE    hPal, hOldPal;
				BOOL        bRes;
				
				GetObject( hBitmap, sizeof(DIBSECTION), &ds );
				if( GetDeviceCaps( hDC, RASTERCAPS ) & RC_PALETTE )
				{   // if it's a palette device, select and realize a palette
					// as a background palette (won't cause a problem is the
					// palette was not selected in the foreground in the main app
					hPal = ptCreatePaletteForDIBSection( hBitmap );
					hOldPal = SelectPalette( hDC, hPal, TRUE );
					RealizePalette( hDC );
				}
				if( GetDeviceCaps( hDC, TECHNOLOGY ) == DT_RASDISPLAY )
				{ // going to the screen, use StretchBlt()
					HDC hMemDC;
					HBITMAP hOldBitmap;
					
					hMemDC = CreateCompatibleDC( hDC  );
					hOldBitmap = (HBITMAP)SelectObject( hMemDC, hBitmap );
					bRes = StretchBlt( hDC, pxdRect->left, pxdRect->top, 
						pxdRect->right-pxdRect->left, pxdRect->bottom-pxdRect->top, 
						hMemDC, 0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight, SRCCOPY );
					SelectObject( hMemDC, hOldBitmap );
					DeleteDC( hMemDC );
				}
				else
				{ // going to the printer, use StretchDIBits()
					LPBITMAPINFO    pbmi;
					
					// if the printer is palettized, 
					pbmi = ptGetBITMAPINFOForDIBSection( hBitmap );
					bRes = (GDI_ERROR != StretchDIBits( hDC, pxdRect->left, pxdRect->top, 
						pxdRect->right-pxdRect->left, pxdRect->bottom-pxdRect->top,
						0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBits, 
						pbmi, DIB_RGB_COLORS, SRCCOPY ));
					free( pbmi );
				}
				if( GetDeviceCaps( hDC, RASTERCAPS ) & RC_PALETTE )
				{
					SelectPalette( hDC, hOldPal, TRUE );
					DeleteObject( hPal );
				}
				return bRes;
			}
			
	};
	// Construction
public:
	CMfcDlgClientMainDlg(CWnd* pParent = NULL);	// standard constructor
	
private:
    CClientProxy*   m_pClientProxy;
	CMyToolBar		m_myToolBar;
    CMyBmp*  m_pBmp;
	char*    m_pBuf;
	
	// Dialog Data
	//{{AFX_DATA(CMfcDlgClientMainDlg)
	enum { IDD = IDD_MfcDlgClientMain_DIALOG };
	CStaticClient	m_ClientView;
	//}}AFX_DATA
	
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CMfcDlgClientMainDlg)
public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
	virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
	//}}AFX_VIRTUAL
	
	// Implementation
protected:
	HICON m_hIcon;
	
	// Generated message map functions
	//{{AFX_MSG(CMfcDlgClientMainDlg)
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	afx_msg void OnBtnSnapshot();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
private: 
public:
	
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MfcDlgClientMainDLG_H__66945FE6_6A79_49D6_9BB3_8F589F2A4CC6__INCLUDED_)
